/**
  ******************************************************************************
  * @file    TCP_ConnClient.c
  * @author  exatron
  * @version V1.0.0
  * @date    segunda, 22 de dezembro de 2014
  * @brief   Função para conectar a um socket server.
  ******************************************************************************
  * @attention
  *
  *
  ******************************************************************************
  */

/** @addtogroup TCP
  * @{
  */

/* Includes ------------------------------------------------------------------*/
#include <common.h>

/* Private variables ---------------------------------------------------------*/
extern Socket_t sock[N_SOCKS];

extern FIFO_t isrx_fifo;

extern BooleanType_t ISRINGS;
extern BooleanType_t ISCLOSE;

/* External functions --------------------------------------------------------*/

/** @defgroup TCP_Functions
  * @{
  */

/**
  * @brief  Função para conectar a um socket server.
  * @param  SocketID_t: ID do socket client
  * @param  char *ip: IP ou DNS do server
  * @param  int porta: Porta a se conectar
  * @retval Devolve pela serial Result_t
  */
void TCP_ConnClient(SocketID_t id, char *ip, int porta)
{
	struct hostent *server;

	/* Se já possuia conexão, fecha*/
	if(sock[id].clifd > 0)
	{
  		/* Fecha sock */
		close(sock[id].clifd);

		/* Informa Desconexão */
		if(ISRINGS == TRUE)
		{
			aux_USART0_puts("%s=%d;%d\r\n", "SCK_CLOS", id, Result_Ok);
		}

		/* Limpa estrutura do socket */
		aux_ClearSocket(id);

	}

    /* Verifica se o socket esta aberto */
    if(sock[id].status != Status_SocketClosed)
    {
		aux_USART0_puts("%s=%d;%d\r\n", "TCP_CNC", id, Result_AlreadyExists);
		aux_SetBusy(FALSE);
		return;
    }

    /* Verifica se possui timeout válido */
    if(aux_CFG_GetTimeOutSocket() == -1)
    {
    	aux_USART0_puts("%s=%d;%d\r\n", "TCP_CNC", id, Result_Error);
    	aux_SetBusy(FALSE);
    	return;
    }

	/* Verifica se possui internet */
	if(aux_WF_PingIP("google.com") != Result_Ok)
	{
		aux_USART0_puts("%s=%d;%d\r\n", "TCP_CNC", id, Result_NoCloud);
		aux_SetBusy(FALSE);
		return;
	}

	if((server=gethostbyname(ip)) == NULL)
	{
		aux_USART0_puts("%s=%d;%d\r\n", "TCP_CNC", id, Result_BadArgument);
		aux_SetBusy(FALSE);
		return;
	}

    /* Zera estrutura do socket */
    aux_ClearSocket(id);

    /* Abre o socket */
    sock[id].clifd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock[id].clifd < 0)
    {
		aux_USART0_puts("%s=%d;%d\r\n", "TCP_CNC", id, Result_OnOpen);
		aux_ClearSocket(id);
		aux_SetBusy(FALSE);
		return;
    }

    /* Seta id e informações de endereço */
    sock[id].ID = id;
    sock[id].seraddr.sin_port = htons(porta);
    sock[id].seraddr.sin_family = AF_INET;
    sock[id].seraddr.sin_addr = *((struct in_addr *)server->h_addr);

    if(connect(sock[id].clifd,(struct sockaddr *)&sock[id].seraddr,sizeof(sock[id].seraddr))<0)
    {
		aux_USART0_puts("%s=%d;%d\r\n", "TCP_CNC", id, Result_OnConnect);
		aux_ClearSocket(id);
		aux_SetBusy(FALSE);
		return;
    }

    /* Escreve a porta */
    sock[id].porta = porta;

    /* Seta status do socket */
    sock[id].status = Status_SocketConnected;

    /* Escreve o tipo de socket */
    sock[id].type = TCP_CLIENT;

    /* Informa Conexão */
    aux_USART0_puts("%s=%d;%d\r\n", "TCP_CNC", id, Result_Ok);

    aux_SetBusy(FALSE);
}

/**
  * @brief  Trata recebimento do socket.
  * @param  Nenhum
  * @retval Nenhum
  */
void TCP_ConnClient_recv(SocketID_t id)
{
	char buf_temp[RX_BUF_LEN];

	bzero(buf_temp, sizeof(buf_temp));
	if(sock[id].clifd > 0)
		sock[id].nb_rec = read(sock[id].clifd, buf_temp, RX_BUF_LEN-1);
	else
		return;

  	if(sock[id].nb_rec > 0)
   	{
   		sock[id].istimeout = 0;

   		fifo_write(&sock[id].fifo_rx, buf_temp, sock[id].nb_rec);

   		if(sock[id].isrx == NoRead)
   		{
   			sock[id].isrx = IsRead;
   			fifo_write(&isrx_fifo, &id, 1);
   			if(ISRINGS == TRUE)
   			{
				aux_SendSignal("SCK_IRDR=%d;%d\r\n", sock[id].ID, Result_Ok);
   			}
   		}
   	}
    /* Erro no recebimento */
  	else
  	{
  		/* Fecha sock */
		if(sock[id].clifd > 0)
			close(sock[id].clifd);

		/* Informa Desconexão */
		if(ISRINGS == TRUE || ISCLOSE == TRUE)
		{
			aux_USART0_puts("%s=%d;%d\r\n", "SCK_CLOS", id, Result_Ok);
			ISCLOSE = FALSE;
		}

		/* Limpa estrutura do socket */
		aux_ClearSocket(id);
  	}
}

/**
  * @}
  */

/**
  * @}
  */








